package io.hellsinger.vortex.service.storage

import io.hellsinger.vortex.Dispatchers
import io.hellsinger.vortex.service.notification.TransactionNotifier
import io.hellsinger.vortex.service.storage.transaction.StorageTransaction
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicInteger

class TransactionController(
    private val notifier: TransactionNotifier,
    private val dispatchers: Dispatchers,
) {
    private val scope = CoroutineScope(dispatchers.io + SupervisorJob())
    private val ids = AtomicInteger(0)

    fun registerTransaction(transaction: StorageTransaction): PendingTransaction {
        transaction.id = ids.getAndIncrement()
        return PendingTransaction(transaction)
    }

    fun cancelAll() = scope.cancel()

    inner class PendingTransaction(
        private val original: StorageTransaction,
    ) {
        fun run() {
            val job =
                scope.launch {
                    original.attachNotificationController(notifier)
                    original.perform()
                }
            job.invokeOnCompletion { original.detachNotificationController() }
        }
    }
}
